﻿namespace Whut.ObjectSharePointMapper.Internals
{
    using System;
    using System.Collections.Generic;
    using Microsoft.SharePoint;

    public class Session : ISession
    {
        private SPWeb web;

        internal MetaDataStore metaDataStore;

        internal SessionLevelCache sessionLevelCache;

        internal EntityHydrater entityHydrater;

        #region SharePoint Actions

        private FindByIdAction findByIdAction;

        private FindAllAction findAllAction;

        private InsertAction insertAction;

        private UpdateAction updateAction;

        private DeleteAction deleteAction;

        #endregion

        public Session(SPWeb web, MetaDataStore metaDataStore)
        {
            this.web = web;
            this.metaDataStore = metaDataStore;
            this.sessionLevelCache = new SessionLevelCache();
            this.entityHydrater = new EntityHydrater(this.metaDataStore, this.sessionLevelCache);
            this.findByIdAction = new FindByIdAction(this.web, this.metaDataStore, this.sessionLevelCache, this.entityHydrater);
            this.findAllAction = new FindAllAction(this.web, this.metaDataStore, this.sessionLevelCache, this.entityHydrater);
            this.insertAction = new InsertAction(this.web, this.metaDataStore, this.sessionLevelCache, this.entityHydrater);
            this.updateAction = new UpdateAction(this.metaDataStore, this.sessionLevelCache, this.entityHydrater);
            this.deleteAction = new DeleteAction(this.metaDataStore, this.sessionLevelCache, this.entityHydrater);
        }

        public TEntity Find<TEntity>(int id)
        {
            return this.findByIdAction.Find<TEntity>(id);
        }

        public IEnumerable<TEntity> FindAll<TEntity>()
        {
            return this.findAllAction.FindAll<TEntity>();
        }

        public TEntity Insert<TEntity>(TEntity entity)
        {
            return this.insertAction.Insert(entity);
        }

        public void Update<TEntity>(TEntity entity)
        {
            this.updateAction.Update(entity);
        }

        public void Delete<TEntity>(TEntity entity)
        {
            this.deleteAction.Delete(entity);
        }

        public IQuery<TEntity> CreateQuery<TEntity>()
        {
            return new Query<TEntity>(this.web, this.metaDataStore, this.entityHydrater);
        }

        public User FindUser(int id)
        {
            if (id < 1)
            {
                return null;
            }

            try
            {
                SPUser user = this.web.SiteUsers.GetByID(id);
                return new User(user.ID, user.Name, user.LoginName, user.Email);
            }
            catch (SPException ex)
            {
                return null;
            }
        }

        public User FindUser(string loginName)
        {
            if (string.IsNullOrEmpty(loginName))
            {
                return null;
            }

            try
            {
                SPUser user = this.web.SiteUsers[loginName];
                return new User(user.ID, user.Name, user.LoginName, user.Email);
            }
            catch (SPException ex)
            {
                return null;
            }
        }
    }
}
